/***********************************************************************************
 * 文件名： rhc.c
 * 版本： 12
 * 说明：
 * 		RHC(Resistance heating controller 电阻加热控制器)，通过PWM控制发热电阻获得的电压值来
 *  控制发热，实现按照指定电压、功率、温度进行加热。
 *      目前只支持固定PWM占空比、平均电压。
 *      注意：
 * 修改记录：
 * 	2021/04/21: 初版。 刘言。
 *  2021/05/07: 增加空载检测功能。刘言。
 *  2021/06/29: 增加正推ADC模式（模式1）支持。
 *  2021/07/07: 增加工作模式静态选择功能，增加 恒定PWM占空比模式 。
 *  2021/07/12: 增加模式切换功能。
 *  2021/07/14: 增加输出端口分压电阻比例设置。
 *  2021/07/15: 增加 负载已装入 事件： _RHC_USE_LOADED_EVENT 。现在可以同时发送多个事件。
 *  2021/07/23: 输出端口分压电阻支持反推ADC模式 和 固定输出模式。现在输出的PWM占空比可以是0~255.
 *  2022/04/13: 实现恒功率输出模式。黄均铭
 *  2023/09/06: 添加伪功率模式，多通道输出。黄均铭【未完成】
 *  2023/10/11: 添加电流检测IC模式
 *  2024/01/12: 添加回调函数配置。黄均铭
 ***********************************************************************************/
#include "rhc.h"
#include "..\..\polsys.h"

#if _RHC_AD_MODE == 0
#define _RHC_VREFADV_LIMIT (rhc_adc_t)((u32)_RHC_VREF_VOLTAGE * (_RHC_FULL_ADV + 1) / _RHC_VBAT_LIMIT)
#else
#define _RHC_VBATADV_LIMIT (rhc_adc_t)((u32)_RHC_VBAT_LIMIT * _RHC_VBAT_LOW_RES * (_RHC_FULL_ADV + 1) / (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) / _RHC_ADC_VREF)
#endif

// 没电计数
static u8 RHC_mNotBatNum;

#ifdef _RHC_USE_MODE_SWITCH
rhc_mode_t _RHC_mMode = (rhc_mode_t)_RHC_MODE;
#endif

u16 _RHC_mTarget; // 目标值

rhc_adc_t RHC_mOutAdv;
#if _RHC_AD_MODE == 0
rhc_adc_t RHC_mVrefAdv;
#else
rhc_adc_t RHC_mVbatAdv;
#endif

#ifdef _RHC_USE_CURRENT
rhc_adc_t RHC_mDivAdv;
#endif

#ifdef _RHC_USE_ACTUAL_PARAM
u16 RHC_mActualOutParam;
#endif

static bit RHC_mRun = false;             // RHC组件运行标记
static bit RHC_mNeedAdv, RHC_mFinishAdv; // 需要获取新的AD值、已处理获取的值
static rhc_ev_t RHC_mEvent;

#if (_RHC_OC_ALLOW_CNT > 0)
static u8 RHC_mOCCnt; // 连续检测到过流的次数
#endif

#if (defined _RHC_USE_LOAD_CHECK) || (defined _RHC_USE_NOLOAD_HINT)
static rhc_load_status_t RHC_mLoadStatus = RHC_LOAD_NULL; // 负载状态
static u8 RHC_mLoadCnt;                                   // 负载取下与负载接入滤波
#endif

#if _RHC_OUT_CHANNEL > 1 && _RHC_MCH_MODE == 2
// 每个通道启动标记
static bit RHC_mCh1Enable, RHC_mCh2Enable;
#if _RHC_OUT_CHANNEL > 2
static bit RHC_mCh3Enable;
#endif
#if _RHC_OUT_CHANNEL > 3
static bit RHC_mCh4Enable;
#endif
#endif

#ifndef POLSYS_LITE
static polsys_task_t mTask;
void RHC_Task();
#endif

#ifdef _RHC_USE_CALLBACK
static rhc_event_callback_t RHC_EventCallback = NULL;

#else
// 声明引用事件通知函数（避免使用函数指针的妥协）
// 在你的应用代码中定义这个函数用于接收事件
void RHC_Event(rhc_ev_t e);

#endif

// 外部事件，这些函数由外部模块调用，用来通知本模块事件发生了

// PWM周期的 ON 跳变（开启输出）
void RHC_EvPWMOutON()
{
    if (RHC_mRun)
    {
        if (RHC_mFinishAdv)
        {
            RHC_mFinishAdv = false;
            RHC_mNeedAdv = true;
        }

#if _RHC_AD_MODE == 1
        _RHC_SetADCVrefVDD();
#endif
#if _RHC_OUT_CHANNEL > 1 && _RHC_MCH_MODE == 2
        if (RHC_mCh1Enable)
        {
            _RHC_StartADC(_RHC_ADCH_OVAL);
        }
        else if (RHC_mCh2Enable)
        {
            _RHC_StartADC(_RHC_ADCH_OVAL2);
        }
#if _RHC_OUT_CHANNEL > 2
        else if (RHC_mCh3Enable)
        {
            _RHC_StartADC(_RHC_ADCH_OVAL3);
        }
#endif
#if _RHC_OUT_CHANNEL > 3
        else if (RHC_mCh4Enable)
        {
            _RHC_StartADC(_RHC_ADCH_OVAL4);
        }
#endif
#else
        _RHC_StartADC(_RHC_ADCH_DIV); // 输出开启时立即采集端口电压AD值
#endif
    }
}

// AD转换完成
void RHC_EvADCCompleted(rhc_adc_t adv)
{
    if (RHC_mRun && _RHC_OutIsON()) // 输出MOS是开启的
    {
        u8 ch = Adc_GetCH();
#ifdef _RHC_USE_CURRENT
        if (ch == _RHC_ADCH_DIV)
        {
            if (adv > (rhc_adc_t)(_RHC_OC_ADVH)) // 过流检测
            {
#if (_RHC_OC_ALLOW_CNT > 0)
                RHC_mOCCnt++; // 连续检测到过流的次数+1
                if (RHC_mOCCnt >= _RHC_OC_ALLOW_CNT + 1)
#endif
                {
                    _RHC_Brake(); // 刹车，立即停止输出
                    RHC_mRun = false;
                    RHC_mEvent = RHC_EV_SHORT_OUT;
                }
#if (_RHC_OC_ALLOW_CNT > 0)
                else
                {
#if (_RHC_KEEP_ADC == 0)
#if _RHC_AD_MODE == 1
                    _RHC_SetADCVrefVDD();
#endif
                    _RHC_StartADC(_RHC_ADCH_DIV); // MOS是开启的就不停的转换
#endif
                }
#endif
            }
            else
            {
#if (_RHC_OC_ALLOW_CNT > 0)
                RHC_mOCCnt = 0;
#endif
                if (RHC_mNeedAdv) // 需要新的AD值
                {
                    RHC_mDivAdv = adv;
#if (_RHC_KEEP_ADC)
                    ch = _RHC_ADCH_OVAL; // 下一次转换VREF通道
#else
                    _RHC_StartADC(_RHC_ADCH_OVAL);
#endif
                }
            }
        }
        else
#endif
            if (ch == _RHC_ADCH_OVAL) // 是OVAL通道
        {
#ifdef _RHC_USE_CURRENT
            if (RHC_mNeedAdv) // 需要新的AD值
            {
                RHC_mOutAdv = adv;
            }
#if (_RHC_KEEP_ADC)
#if _RHC_AD_MODE == 0
            ch = _RHC_ADCH_VREF; // 下一次转换VREF通道
#else
            ch = _RHC_ADCH_VBAT; // 下一次转换VBAT通道
#endif
#else
#if _RHC_AD_MODE == 0
            _RHC_StartADC(_RHC_ADCH_VREF);
#else
            _RHC_SetADCVrefVref();
            _RHC_StartADC(_RHC_ADCH_VBAT);
#endif
#endif

#else
            if ((adv < _RHC_OC_ADVH)
#if (_RHC_OC_ADVL > 0)
                && (adv > _RHC_OC_ADVL)
#endif
                    )         // 过流检测
            {
#if (_RHC_OC_ALLOW_CNT > 0)
                RHC_mOCCnt++; // 连续检测到过流的次数+1
                if (RHC_mOCCnt >= _RHC_OC_ALLOW_CNT + 1)
#endif
                {
                    _RHC_Brake(); // 刹车，立即停止输出
                    RHC_mRun = false;
                    RHC_mEvent = RHC_EV_SHORT_OUT;
                }
#if (_RHC_OC_ALLOW_CNT > 0)
                else
                {
#if (_RHC_KEEP_ADC == 0)
#if _RHC_AD_MODE == 1
                    _RHC_SetADCVrefVDD();
#endif
                    _RHC_StartADC(_RHC_ADCH_OVAL); // MOS是开启的就不停的转换
#endif
                }
#endif
            }
            else
            {
#if (_RHC_OC_ALLOW_CNT > 0)
                RHC_mOCCnt = 0;
#endif
                if (RHC_mNeedAdv) // 需要新的AD值
                {
                    RHC_mOutAdv = adv;
#if (_RHC_KEEP_ADC)
#if _RHC_AD_MODE == 0
                    ch = _RHC_ADCH_VREF; // 下一次转换VREF通道
#else
                    ch = _RHC_ADCH_VBAT; // 下一次转换VBAT通道
#endif
#else
#if _RHC_AD_MODE == 0
                    _RHC_StartADC(_RHC_ADCH_VREF);
#else
                    _RHC_SetADCVrefVref();
                    _RHC_StartADC(_RHC_ADCH_VBAT);
#endif
#endif
                }
            }
#endif
        }
        else                  /*if(ch == _RHC_ADCH_VREF)*/
        {
            if (RHC_mNeedAdv) // 需要新的AD值
            {
#if _RHC_AD_MODE == 0
                RHC_mVrefAdv = adv;
#else
                RHC_mVbatAdv = adv;
#endif
                RHC_mNeedAdv = false;
            }
#if (_RHC_KEEP_ADC)
            ch = _RHC_ADCH_DIV;
#endif
        }
#if (_RHC_KEEP_ADC)
#if _RHC_AD_MODE == 1
        if (ch == _RHC_ADCH_VREF)
        {
            _RHC_SetADCVrefVref();
        }
        else
        {
            _RHC_SetADCVrefVDD();
        }
#endif
        _RHC_StartADC(ch); // MOS是开启的就不停的转换
#endif
    }
}

// 对外提供的API

// 初始化
// 内部已经初始化了 PWM 发生器
void RHC_Init()
{
    _RHC_InitPWM();
#ifndef POLSYS_LITE
    Polsys_TaskInit(&mTask, RHC_Task, 10);
#endif
}

// 通过OAVL的AD值计算阻值
u16 RHC_AdvOvalToRes(rhc_adc_t advout)
{
    return (((u32)(_RHC_RES_REF * _RHC_RES_MUL * 16) * advout / (((_RHC_FULL_ADV + 1) - advout) * 16)) - _RHC_RES_DIFF);
}

#ifdef _RHC_USE_LOAD_RES
// 负载阻值更新。请注意：内部不包含中断开关操作。
#if _RHC_LOAD_NUM > 1
#ifdef _RHC_USE_CURRENT
u16 RHC_UpdateRes(u8 ch, u8 adc_ch, u8 div_ch)
#else
u16 RHC_UpdateRes(u8 ch, u8 adc_ch)
#endif
#else
u16 RHC_UpdateRes(void)
#endif
{
#ifdef _RHC_USE_CURRENT
#if _RHC_LOAD_NUM > 1
// 多通道带电流IC的方案
#error "多通道电流检测IC方案暂无计算, 需完善"
#endif
    // 没短路，多次采集取平均值
    u8 i;
    rhc_adc_t advout1, advdiv;
    u32 sumout, sumdiv, res;
    // 供电
    _RHC_StartPWM();
    _RHC_SetPWM(255);
    OUTEN_ON;
    // 延时等待 - A39等雾化器的启动需要一点点时间，还需要注意防止过功率导致A39关闭mos
    Delay_ms(20);
    sumout = 0;
    sumdiv = 0;
    for (i = 0; i < 8; i++)
    {
        _RHC_SetPWM(0);
        OUTEN_OFF;
        // 延时等待
        Delay_ms(2);
        _RHC_SetPWM(255);
        OUTEN_ON;
        // 准备采集
        _RHC_BeforeGetLoadAdv();
        Delay_ms(1);
        advout1 = _RHC_GetAdv(ADCH_OVAL);
        advdiv = _RHC_GetAdv(ADCH_DIV);
        // 结束
        _RHC_AfterGetLoadAdv();
        sumout += advout1;
        sumdiv += advdiv;
    }
    _RHC_Brake();
    advout1 = sumout / 8;
    advdiv = sumdiv / 8;
    if (advdiv < (u16)(_RHC_VBAT_LIMIT * 1000.0f / _APP_NO_LOAD_RES / _RHC_CURRENT_CNT)) // 一般
    {
        _RHC_SetRes(0, 0xFFFF);
        return 0xFFFF;
    }
    else
    {
        res = (u32)(1000.0f * 0.99f / _RHC_CURRENT_CNT) * advout1 / advdiv;
        _RHC_SetRes(0, res);
        return res;
    }
#else

#if _RHC_LOAD_NUM > 1
    // 多通道方案
#error "多通道方案暂不支持, 需完善"
#else
    // 单通道方案
    u8 i;
    rhc_adc_t advout;
    u32 sumout;

    // 没短路，多次采集取平均值
    sumout = 0;
    for (i = 0; i < 8; i++)
    {
        // 准备采集
        _RHC_BeforeGetLoadAdv();
        OUTEN_ON;
        Delay_us(ADC_DELAY);
        advout = _RHC_GetAdv(ADCH_OVAL);
        OUTEN_OFF;
        // 结束
        _RHC_AfterGetLoadAdv();
        sumout += advout;
        // 延时等待
        Delay_ms(1);
    }
    advout = sumout / 8;

#ifdef _RHC_NO_LOAD_ADV
    if (advout >= (u16)_RHC_NO_LOAD_ADV)
    {
        return 0x3FFF;
    }
    else
#endif
    {
        return (((u32)(_RHC_RES_REF * _RHC_RES_MUL * 16) * advout / (((_RHC_FULL_ADV + 1) - advout) * 16)) - _RHC_RES_DIFF);
    }
#endif
#endif
}
#endif

// 开始运作，将会开始按照设定参数输出
void RHC_Start()
{
    // 初始化部分参数
#if (_RHC_OC_ALLOW_CNT > 0)
    RHC_mOCCnt = 0;
#endif

#if (!defined _RHC_USE_LOAD_CHECK) && (defined _RHC_USE_NOLOAD_HINT)
    // 启动空载提示，但是未启用负载检测
    RHC_mLoadStatus = RHC_LOAD_NULL;
    RHC_mLoadCnt = 0;
#endif

#if (defined _RHC_USE_LOAD_CHECK) && (defined _RHC_USE_NOLOAD_HINT)
    // 启用空载提示，并且启用了负载检测
    if (RHC_mLoadStatus == RHC_NO_LOAD)
    {
        RHC_mEvent = RHC_EV_NO_LOAD;
        return;
    }
#endif

    RHC_mNeedAdv = true;
    RHC_mFinishAdv = false;
    RHC_mEvent = RHC_EV_NULL;
    RHC_mNotBatNum = 0;
    RHC_mRun = true;
    _RHC_SetPWM(255);
    _RHC_StartPWM();

#if (defined _RHC_USE_LOAD_RES) && ((defined _RHC_USE_MODE_SWITCH) || (_RHC_MODE == 3)) && (!defined _RHC_USE_CURRENT)
#if _RHC_POWER_TSELLE == 1
    // 如果可切换或者模式为3
    _RHC_BeforeLoadCheck();
#if _RHC_LOAD_NUM > 1
#error "多通道待完善"
#else
    _RHC_SetRes(0, RHC_UpdateRes());
#endif
    _RHC_AfterLoadCheck();
#endif
#endif
}

void RHC_Stop()
{
    RHC_mRun = false;
    _RHC_Brake(); // 刹车，立即停止输出
}

// 间隔10~100ms执行一次
void RHC_Task()
{
    if (RHC_mRun)
    {
        u8 new_pwm;

        if (!RHC_mFinishAdv && !RHC_mNeedAdv) // 说明AD值未处理，并且已经获取了
        {
#if (defined _RHC_USE_NOLOAD_HINT)
#ifdef _RHC_USE_CURRENT
            if (RHC_mLoadStatus != RHC_NO_LOAD && RHC_mDivAdv <= (rhc_adc_t)_RHC_NO_LOAD_ADV)
#else
            if (RHC_mLoadStatus != RHC_NO_LOAD && RHC_mOutAdv >= (rhc_adc_t)_RHC_NO_LOAD_ADV)
#endif
            {
                RHC_mLoadCnt++;
                if (RHC_mLoadCnt == _RHC_NO_LOAD_ALLOW_CNT)
                {
                    RHC_mLoadStatus = RHC_NO_LOAD;
#if (defined _RHC_USE_NOLOAD_HINT)
                    RHC_mEvent = RHC_EV_NO_LOAD;
#endif
                }
            }
            else
            {
                RHC_mLoadCnt = 0;
            }
#endif
#if _RHC_AD_MODE == 0
            if (RHC_mVrefAdv > _RHC_VREFADV_LIMIT)
#else
            if (RHC_mVbatAdv < _RHC_VBATADV_LIMIT)
#endif
            {
                RHC_mNotBatNum++;
                if (RHC_mNotBatNum >= 10)
                {
                    RHC_Stop();
                    RHC_mEvent = RHC_EV_NO_BATTERY;
                }
            }
            else
            {
                RHC_mNotBatNum = 0;
            }

#ifdef _RHC_USE_MODE_SWITCH
#if _RHC_VALID_MODE & 0x01
            if (_RHC_mMode == RHC_MODE_CONST_PWM)
            {
                new_pwm = _RHC_mTarget;
            }
#endif
#if _RHC_VALID_MODE & 0x02
            if (_RHC_mMode == RHC_MODE_AVG_VOLTAGE)
            {
                u16 out_high_voltage, target_pwm;
                // 电压(平均值)
#if _RHC_AD_MODE == 0
                out_high_voltage = ((rhc_sum_t)(_RHC_VREF_VOLTAGE >> 4) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                out_high_voltage = (rhc_sum_t)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)_RHC_ADC_VREF * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
                // 计算pwm 用U16原因：当输出电压很低，目标电压很高时，可能导致u8的值为103，造成输出电压过低bug
                target_pwm = (u16)16 * _RHC_mTarget / out_high_voltage;
                if (target_pwm > 255)
                    new_pwm = 255;
                else
                    new_pwm = target_pwm;
            }
#endif

#if _RHC_VALID_MODE & 0x04
            if (_RHC_mMode == RHC_MODE_RMS_VOLTAGE)
            {
                if (_RHC_mTarget > 4095)
                {
                    new_pwm = 255;
                }
                else
                {
                    u16 tmp, out_high_voltage;
                    // 恒定有效值模式，根据最大电压和设置电压计算pwm
                    // 计算电压，单位16mV，公式：Umax = Uref * Advout / Advref
#if _RHC_AD_MODE == 0
                    out_high_voltage = ((rhc_sum_t)(_RHC_VREF_VOLTAGE >> 3) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                    out_high_voltage = (rhc_sum_t)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)(_RHC_VREF_VOLTAGE >> 3) * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
                    // 恒有效值pwm计算公式(Umax:MOS导通时的输出电压，Uh：有效值)：
                    // P = Umax^2 / R * Pwm / 255 = Uh^2 / R
                    // Umax^2 * Pwm / 255 = Uh^2
                    // Pwm = 255 * Uh^2 / Umax^2 ≈ 256 * Uh^2 / Umax^2 = (16 * Uh / Umax)^2 (用这个算会导致丢失很多精度)
                    //     = (16 * Uh / (Umax / 16) / 16)^2 = (16 * Uh / (Umax / 16))^2 / 256 (在U16范围内尽量保持精度)
                    // 计算pwm
                    tmp = (u16)16 * _RHC_mTarget / out_high_voltage;
                    if (tmp > 127)
                        new_pwm = 255;
                    else
                        new_pwm = (tmp * tmp) >> 6;
                }
            }
#endif

#if _RHC_VALID_MODE & 0x08
            if (_RHC_mMode == RHC_MODE_POWER)
            {
                // 恒功率模式
#if _RHC_POWER_TSELLE == 0
                // 实时变化
#if _RHC_AD_MODE == 0
                u8 battery_voltage, out_high_voltage, out_high_power;
                u16 target_pwm;
                // 计算 Ubat ,单位16mV（最大4080mV）
                battery_voltage = (u8)((rhc_sum_t)(_RHC_VREF_VOLTAGE * ((_RHC_FULL_ADV + 1) / 16)) / RHC_mVrefAdv);
                // 计算 输出电压 ,单位16mV（最大4080mV）////////////考虑直接算电压差可能有优化
                out_high_voltage = (u8)((rhc_sum_t)RHC_mOutAdv * battery_voltage * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / (_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1)));
                // 计算功率 单位256mW
                out_high_power = ((u16)out_high_voltage * (battery_voltage - out_high_voltage) * 16 / (u8)(_RHC_RES_REF * 16));
                // 计算pwm
                target_pwm = _RHC_mTarget / out_high_power;

#else
                u8 battery_voltage, out_high_voltage, out_high_power;
                u16 target_pwm;
                // 计算 Ubat ,单位16mV（最大4080mV）
                battery_voltage = (u8)((rhc_sum_t)RHC_mVbatAdv * (_RHC_ADC_VREF * (_RHC_VBAT_LOW_RES + _RHC_VBAT_HIGH_RES) / 16) / (_RHC_VBAT_LOW_RES * (_RHC_FULL_ADV + 1)));
                // 计算 输出电压 ,单位16mV（最大4080mV）////////////考虑直接算电压差可能有优化
                out_high_voltage = (u8)((rhc_sum_t)RHC_mOutAdv * battery_voltage * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / (_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1)));
                // 计算功率 单位256mW
                out_high_power = ((u16)out_high_voltage * (battery_voltage - out_high_voltage) * 16 / (u8)(_RHC_RES_REF * 16));
                // 计算pwm
                target_pwm = _RHC_mTarget / out_high_power;
#endif
#else
                // 首个阻值 或者 伪功率
                u16 out_high_voltage, out_high_power;
                u16 target_pwm;
#if _RHC_AD_MODE == 0
                // 计算 输出电压, 单位mV
                out_high_voltage = ((u32)(_RHC_VREF_VOLTAGE) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                // 计算 输出电压, 单位mV
                out_high_voltage = (u32)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)(_RHC_ADC_VREF) * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
#if _RHC_LOAD_NUM > 1
#error "多负载输出控制待完善"
#else
                // 计算功率 单位mW
                out_high_power = ((u32)out_high_voltage * out_high_voltage / (_RHC_GetRes(0)));
#endif
                // 计算pwm
                target_pwm = (u32)256 * _RHC_mTarget / out_high_power;
#endif
                // 判断是否超过最大值
                if (target_pwm > 255)
                {
                    new_pwm = 255;
#ifdef _RHC_USE_ACTUAL_PARAM
                    // 需要计算实际值
                    RHC_mActualOutParam = out_high_power;
#endif
                }
                else
                {
                    new_pwm = target_pwm;
#ifdef _RHC_USE_ACTUAL_PARAM
                    // 需要计算实际值
                    RHC_mActualOutParam = _RHC_mTarget;
#endif
                }
            }
#endif

#else
            // 固定输出模式
            {
#ifdef _RHC_USE_CURRENT
                // 带电流检测IC
#if _RHC_MODE == 3
                // 恒功率模式
#if _RHC_AD_MODE == 0
                u16 out_high_voltage, out_high_current, out_high_power;
                u16 target_pwm;
#if _RHC_OVAL_HIGH_RES != 0
                // 计算 输出电压，单位16mV（最大4080mV）////////////考虑直接算电压差可能有优化
                out_high_voltage = (u32)_RHC_VREF_VOLTAGE * RHC_mOutAdv * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / (_RHC_OVAL_LOW_RES * RHC_mVrefAdv);
#else
                // 计算 输出电压，单位：mV
                out_high_voltage = (u32)_RHC_VREF_VOLTAGE * RHC_mOutAdv / RHC_mVrefAdv;
#endif
                // 计算 输出电流，单位：mA
                out_high_current = (u32)(_RHC_VREF_VOLTAGE * _RHC_CURRENT_CNT) * RHC_mDivAdv / RHC_mVrefAdv;

                //_RHC_SetRes(0, (u32)1000 * out_high_voltage / out_high_current);

                // 计算伪功率 单位：mW
                out_high_power = (u32)out_high_voltage * out_high_current / 1000;

                // 计算pwm
                if (out_high_power > 0)
                    target_pwm = (u32)_RHC_mTarget * 256 / out_high_power;
                else
                    target_pwm = 256;
#else
                u16 battery_voltage, out_high_voltage, out_high_current, out_high_power;
                u16 target_pwm;
                // 计算 Ubat,单位：mV
                battery_voltage = ((u32)RHC_mVbatAdv * (_RHC_ADC_VREF * (_RHC_VBAT_LOW_RES + _RHC_VBAT_HIGH_RES)) / (_RHC_VBAT_LOW_RES * (_RHC_FULL_ADV + 1)));
                // 计算 输出电压,单位：mV
                out_high_voltage = ((u32)RHC_mOutAdv * battery_voltage / ((_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1)) / (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
                // 计算 输出电流，单位：mA
                out_high_current = (u32)RHC_mDivAdv * battery_voltage / (u32)((float)(_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1)) / (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_CURRENT_CNT));
                // 计算伪功率 单位：mW
                out_high_power = (u32)out_high_voltage * out_high_current / 1000;
                // 计算pwm
                target_pwm = (u32)_RHC_mTarget * 256 / out_high_power;
#endif
                // 判断是否超过最大值
                if (target_pwm > 255)
                {
                    new_pwm = 255;
#ifdef _RHC_USE_ACTUAL_PARAM
                    // 需要计算实际值
                    RHC_mActualOutParam = out_high_power;
#endif
                }
                else
                {
                    new_pwm = target_pwm;
#ifdef _RHC_USE_ACTUAL_PARAM
                    // 需要计算实际值
                    RHC_mActualOutParam = _RHC_mTarget;
#endif
                }

#elif _RHC_MODE == 4
                                         // 恒温模式
#error "此模式未完成"
#else
#error "不支持的模式"
#endif

#else
                // 不带电流检测IC
#if _RHC_MODE == 0
                // 恒PWM
                target_pwm = _RHC_mTarget;
#elif _RHC_MODE == 2
                u16 tmp, out_high_voltage;
                // 恒定有效值模式，根据最大电压和设置电压计算pwm
                // 计算电压，单位16mV，公式：Umax = Uref * Advout / Advref
#if _RHC_AD_MODE == 0
                out_high_voltage = ((rhc_sum_t)(_RHC_VREF_VOLTAGE >> 3) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                out_high_voltage = (rhc_sum_t)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)(_RHC_ADC_VREF >> 3) * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
                if (_RHC_mTarget > 4095)
                {
                    new_pwm = 255;
                }
                else
                {
                    // 恒有效值pwm计算公式(Umax:MOS导通时的输出电压，Uh：有效值)：
                    // P = Umax^2 / R * Pwm / 255 = Uh^2 / R
                    // Umax^2 * Pwm / 255 = Uh^2
                    // Pwm = 255 * Uh^2 / Umax^2 ≈ 256 * Uh^2 / Umax^2 = (16 * Uh / Umax)^2 (用这个算会导致丢失很多精度)
                    //     = (16 * Uh / (Umax / 16) / 16)^2 = (16 * Uh / (Umax / 16))^2 / 256 (在U16范围内尽量保持精度)
                    // 计算pwm
                    tmp = (u16)16 * _RHC_mTarget / out_high_voltage;
                    if (tmp > 127)
                        new_pwm = 255;
                    else
                        new_pwm = (tmp * tmp) >> 6;
                }
#ifdef _RHC_USE_ACTUAL_PARAM
                // 判断是否超过最大值
                if (new_pwm == 255)
                {
                    // 需要计算实际值
                    RHC_mActualOutParam = out_high_voltage;
                }
                else
                {
                    // 需要计算实际值
                    RHC_mActualOutParam = _RHC_mTarget;
                }
#endif

#elif _RHC_MODE == 3
                // 恒功率模式
#if _RHC_POWER_TSELLE == 0
                // 实时变化
#if _RHC_AD_MODE == 0
#if _RHC_RES_DIFF == 0
                u8 battery_voltage, out_high_voltage, out_high_power;
                u16 target_pwm;
                // 计算 Ubat ,单位16mV（最大4080mV）
                battery_voltage = (u8)((rhc_sum_t)(_RHC_VREF_VOLTAGE * ((_RHC_FULL_ADV + 1) / 16)) / RHC_mVrefAdv);
#if _RHC_RES_DIFF == 0
                // 计算 输出电压 ,单位16mV（最大4080mV）////////////考虑直接算电压差可能有优化
                out_high_voltage = (u8)((rhc_sum_t)RHC_mOutAdv * battery_voltage * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / (_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1)));
#else
                // 计算 输出电压 ,单位16mV（最大4080mV）////////////考虑直接算电压差可能有优化
                out_high_voltage = (u8)((u32)RHC_mOutAdv * battery_voltage * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) * (u32)((_RHC_RES_LOAD - _RHC_RES_DIFF) * 256 / _RHC_RES_LOAD) / (_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1) * 256));
#endif
                // 计算功率 单位256mW
                out_high_power = ((u16)out_high_voltage * (battery_voltage - out_high_voltage) / _RHC_RES_REF);
#define _RHC_POWER_MUL 256
                // 计算pwm
                target_pwm = _RHC_mTarget / out_high_power;

#else
                // 实时功率
                u16 out_high_voltage, out_high_power, out_res;
                u16 target_pwm;
#if _RHC_AD_MODE == 0
                // 计算 输出电压, 单位mV
                out_high_voltage = ((u32)(_RHC_VREF_VOLTAGE) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                // 计算 输出电压, 单位mV
                out_high_voltage = (u32)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)(_RHC_ADC_VREF) * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
#if _RHC_LOAD_NUM > 1
#error "多负载输出控制待完善"
#else
                out_res = RHC_AdvOvalToRes(RHC_mOutAdv);
                // 计算功率 单位mW
                out_high_power = ((u32)out_high_voltage * out_high_voltage / (out_res + _RHC_RES_DIFF));
#define _RHC_POWER_MUL 1
#endif
#if _RHC_RES_DIFF == 0
                // 计算pwm
                target_pwm = (u32)256 * _RHC_mTarget / out_high_power;
#else
                // 计算pwm
                target_pwm = ((u32)out_res * _RHC_mTarget / (out_res - _RHC_RES_DIFF)) * 256 / out_high_power;
#endif
#endif

#else
                u8 battery_voltage, out_high_voltage, out_high_power;
                u16 target_pwm;
                // 计算 Ubat ,单位16mV（最大4080mV）
                battery_voltage = (u8)((rhc_sum_t)RHC_mVbatAdv * (_RHC_ADC_VREF * (_RHC_VBAT_LOW_RES + _RHC_VBAT_HIGH_RES) / 16) / (_RHC_VBAT_LOW_RES * (_RHC_FULL_ADV + 1)));
                // 计算 输出电压 ,单位16mV（最大4080mV）////////////考虑直接算电压差可能有优化
                out_high_voltage = (u8)((rhc_sum_t)RHC_mOutAdv * battery_voltage * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / (_RHC_OVAL_LOW_RES * (_RHC_FULL_ADV + 1)));
                // 计算功率 单位256mW
                out_high_power = ((u16)out_high_voltage * (battery_voltage - out_high_voltage) / _RHC_RES_REF);
#define _RHC_POWER_MUL 256
                // 计算pwm
                target_pwm = _RHC_mTarget / out_high_power;
#endif
#else
                // 首个阻值 或者 伪功率
                u16 out_high_voltage, out_high_power;
                u16 target_pwm;
#if _RHC_AD_MODE == 0
                // 计算 输出电压, 单位mV
                out_high_voltage = ((u32)(_RHC_VREF_VOLTAGE) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                // 计算 输出电压, 单位mV
                out_high_voltage = (u32)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)(_RHC_ADC_VREF) * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
#if _RHC_LOAD_NUM > 1
#error "多负载输出控制待完善"
#else
                // 计算功率 单位mW
                out_high_power = ((u32)out_high_voltage * out_high_voltage / (_RHC_GetRes(0) + _RHC_RES_DIFF));
#endif
#define _RHC_POWER_MUL 256
#if _RHC_RES_DIFF == 0
                // 计算pwm
                target_pwm = (u32)256 * _RHC_mTarget / out_high_power;
#else
                // 计算pwm
                target_pwm = (u32)256 * _RHC_GetRes(0) * _RHC_mTarget / ((u32)out_high_power * (_RHC_GetRes(0) - _RHC_RES_DIFF));
#endif
#endif
                // 判断是否超过最大值
                if (target_pwm > 255)
                {
                    new_pwm = 255;
#ifdef _RHC_USE_ACTUAL_PARAM
                    // 需要计算实际值
                    RHC_mActualOutParam = (u16)out_high_power * _RHC_POWER_MUL;
#if _RHC_RES_DIFF != 0
                    if (RHC_mActualOutParam > _RHC_mTarget)
                        RHC_mActualOutParam = _RHC_mTarget;
#endif
#endif
                }
                else
                {
                    new_pwm = target_pwm;
#ifdef _RHC_USE_ACTUAL_PARAM
                    // 需要计算实际值
                    RHC_mActualOutParam = _RHC_mTarget;
#endif
                }
#else
                u16 out_high_voltage, target_pwm;
                // 电压(平均值)
#if _RHC_AD_MODE == 0
                out_high_voltage = ((rhc_sum_t)(_RHC_VREF_VOLTAGE >> 4) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES) / _RHC_OVAL_LOW_RES) * RHC_mOutAdv / RHC_mVrefAdv;
#else
                out_high_voltage = (rhc_sum_t)RHC_mOutAdv * RHC_mVbatAdv / (u16)(((u32)(_RHC_FULL_ADV + 1) * (_RHC_FULL_ADV + 1) * _RHC_VBAT_LOW_RES * _RHC_OVAL_LOW_RES) / ((u32)_RHC_ADC_VREF * (_RHC_VBAT_HIGH_RES + _RHC_VBAT_LOW_RES) * (_RHC_OVAL_LOW_RES + _RHC_OVAL_HIGH_RES)));
#endif
                // 计算pwm 用U16原因：当输出电压很低，目标电压很高时，可能导致u8的值为103，造成输出电压过低bug
                target_pwm = (u16)16 * _RHC_mTarget / out_high_voltage;
                if (target_pwm > 255)
                    new_pwm = 255;
                else
                    new_pwm = target_pwm;
#endif
#endif
            }
#endif
            // pwm不得超出范围
            if (new_pwm < _RHC_MIN_PWM)
                new_pwm = _RHC_MIN_PWM;
            // 确保rhc组件还在运行
            _RHC_SetPWM(new_pwm);
            if (!RHC_mRun)
            {
                _RHC_SetPWM(0);
            }
            RHC_mFinishAdv = true;
        }
    }
    else
    {
#ifdef _RHC_USE_LOAD_CHECK
        // 负载接入检测功能
        if (_RHC_GetLoadStatus())
        {
            // 有负载
            if (RHC_mLoadStatus == RHC_LOAD_NULL)
            {
                // 首次初始化
                RHC_mLoadCnt = 0;
                RHC_mLoadStatus = RHC_LOADED;
            }
            else if (RHC_mLoadStatus == RHC_NO_LOAD) // 之前是空载
            {
                if (RHC_mLoadCnt > 0)
                    RHC_mLoadCnt--;
                if (RHC_mLoadCnt == 0)
                {
                    // 标记负载状态，发送负载接入消息
                    RHC_mLoadStatus = RHC_LOADED;
                    RHC_mEvent = RHC_EV_LOADED;
                }
            }
            else
                RHC_mLoadCnt = 0;
        }
        else
        {
            // 空载
            if (RHC_mLoadStatus == RHC_LOAD_NULL)
            {
                // 首次初始化
                RHC_mLoadCnt = _RHC_NO_LOAD_FILTERING_CNT;
                RHC_mLoadStatus = RHC_NO_LOAD;
            }
            else if (RHC_mLoadStatus == RHC_LOADED) // 之前是带载
            {
                RHC_mLoadCnt++;
                if (RHC_mLoadCnt >= _RHC_NO_LOAD_FILTERING_CNT)
                {
                    RHC_mLoadStatus = RHC_NO_LOAD;
                    RHC_mEvent = RHC_EV_UNLOADED;
                }
            }
            else
                RHC_mLoadCnt = _RHC_NO_LOAD_FILTERING_CNT;
        }
#endif
    }
    if (RHC_mEvent != RHC_EV_NULL)
    {
#ifdef _RHC_USE_CALLBACK
        if (RHC_EventCallback != NULL)
        {
            RHC_EventCallback(RHC_mEvent);
        }
#else
        RHC_Event(RHC_mEvent);
#endif
        RHC_mEvent = RHC_EV_NULL;
    }
}

#ifdef _RHC_USE_CALLBACK
void RHC_SetCallBack(rhc_event_callback_t event_callback)
{
    RHC_EventCallback = event_callback;
}

#endif

#ifdef _RHC_USE_LOAD_CHECK
// 获取当前负载状态 true：已连接
bool RHC_GetLoadStatus()
{
    if (RHC_mLoadStatus == RHC_LOADED)
        return true;
    else
        return false;
}
#endif
